YU-NO (windows vers.) script dumper/rebuilder
author: kingshriek
version: 0.2

mesdump.py       script (.MES) dumper
mesrebuild.py    script (.MES) rebuilder

Both are Python 3.x scripts (they will not work with Python 2.x).
Scripts are public domain - do what you want with them.
Feel free to contact me (I hang out in #Ammy and #tlwiki on irc.rizon.net)
regarding bugs/usage.



[SETUP/USAGE]



unpacking:

To unpack the script archive, use crass (http://galcrass.blog124.fc2.com/). 
The archive containing the script files is named MES.ARC. To unpack it, you 
must specifiy the AI5WIN cui plugin. Doing so should leave you with 903 script
files.

Specific command line:
    crage -p <path_to>\MES.ARC -u AI5WIN

	
	
dumping:

To dump the scripts, run mesdump.py on a directory containg the .MES files
that you want. mesdump.py will only process .MES files and ignore files with
other extensions in the directory. Scripts are currently dumped to utf-8 
encoded (without BOM) text files (.MSD extension).

How to run:
	mesdump.py [options] <input_dir> <output_dir>

    options:
      --version      show program's version number and exit
      -h, --help     show this help message and exit
      -R, --recurse  recurse through subdirectories
      -v, --verbose  verbose output
	
	
modifying:

The script dumps are separated into individual commands. Beside each command 
on the left is a label (ending with a ":") that identifies the command. 
Opcodes and most arguments are represented as hex digits. Command arguments 
that are interpreted as script offsets are converted to labels. Any strings 
occuring in the script data will appear in the dump as strings, surrounded 
by double-quote characters (""). Comments are indicated by beginning the line 
with "//". Note: all comments must be entirely on their own line.

To aid in translation, all non-text commands are surrounded by curly braces. 
The point of this is so an editor that supports syntax folding can hide all
not-text lines when interpeting the script dump as a C code, leaving only what
needs to be translated. Since the dumped script files contain a *massive* 
amount of parsed bytecode, I highly recommend doing this while editing. Also, 
each text command is written out twice with the top one commented out. This is
to help with translation by providing a reference to the original Japanese 
text. Text commands are labeled with a "page #" comment as well to aid in
referring to a specific line during the translation/editing process. 
mesrebuild.py has basic support for word-wrapping and repagination, so you do 
not have to worry about the translated lines being too long for the text box.

Regarding text strings, everything within the very first and very last 
double-quote characters are passed directly to the rebuilt .MES file, with
exception of "\protag". YU-NO lets you name your character at the beginning
of the game and the script dumps use "\protag" in place of the command that
reads the protaganist's name. Additional double-quote characters with the
very first and very last are passed to the script, so don't worry about them
getting interpreted as syntax.

On word-wrapping, for it to work properly, the string should not contain any
double-width characters. Also, there are a few sections of the game that have
a NVL-like presentation instead of the usual ADV text box. Those will probably
need to be handled on a special-case basis. The parameters for wordwrapping
are defined at the beginning of the mesrebuild.py script if you want to use
something else. 

At the moment, the word-wrapping code does not work too well with the 
"\protag" marker. A potential fix for this would be to use the maximum length 
of the protagonist's name along newline commands (if the game has them, that 
is). Currently, the word-wrapping just pads the line with spaces, so that's 
why it has trouble with the unknown length. Of course, another option is to 
just force the player to be named Takuya (easy way out). Hey, the Saturn 
version does it, and so does the special disk scenario.

The script dumps also allow for inserting additional commands. You do not need
a label for any commands unless you need to refer to it from another command
which uses a script offset argument. If you do specify a label, there must be
a space between the colon at the end of the label and the start of the 
command.



rebuilding:

To rebuild the modified scripts, run mesrebuild.py on the directory containing
them. mesrebuild.py will only process .MSD files and ignore files with other
extensions in the directory.

How to run:
    mesrebuild.py [options] <input_dir> <output_dir>

    options:
      --version      show program's version number and exit
      -h, --help     show this help message and exit
      -R, --recurse  recurse through subdirectories
      -v, --verbose  verbose output
 
	
	
repacking:

I am not aware of any tool that can repack the data, but the good news is that
you don't have to. In order to make this possible, you need to modify the
AI5WIN.INI file that is located wherever the game was installed. The changes
that need to be made are:

[FILE]
bARCMES=1 change to bARCMES=0

[MES]
bMES=1 change to bMESTYPE=0

This will modifiy the game's behavior to read the .MES files directly rather 
than unpacking them from an archive. Changing them back to their previous 
values will restore the original behavior (reading from MES.ARC archive).

Unfortunately, with this change, all of the .MES files must be in the same 
base directory as the game executable, whether they have been modified or
not. And with there being around 900 of them, it makes things a bit messy. I
haven't yet found out a way to get the game to read them from another
directory.



[APPENDIX]



script file naming format:

The general naming format of the scripts is: 
    <route>[_<subroute>]<location>[_<id>][<sub_id>][I].MES.

where fields enclosed in square brackets [] are optional.

<route> is one of the following:
    (none)    Mitsuki's route
    A         path to epilogue
    B         additional scripts (not really belonging to a particular route)
    C         Ayumi's route
    D         Mio's route
    E         Kanna's route
    F         Kaori's route
    P         prologue
    SP        special disk scenario
    Z         epilogue
	
<subroute> occurs only in Mio's route and the path to epilogue. It refers to 
scripts that pertain to a certain special location in the game (you probably 
know what I'm talking about if you've played it). Values can either be A, B, C 
for Mio's route (different branches) or (none) for the path to epilogue.

<location> is one of the following:
    01        protagonist's room
    02        living room
    03        Ayumi's room
    04        front of protagonist's house
    05        school gate
    06        school hall
    07        school 2nd floor
    08        school study room
    09        school infirmary
    10        school roof
    11        (not used)
    12        front of Mio's house
    13        Mio's room
    14        front of apartment building
    15        Kanna's room
    16        front of samurai residence
    17        samurai residence living room
    18        coast
    19        front of hotel
    20        hotel room
    21        central street
    22        shrine
    23        front of Kanna's room
    24        front of Geo-technics building
    25        cafe
    26        inside Geo-technics building
    27        heights
    28        park
    29        samurai residence garden
    30        well
    31        front of storehouse
    32        inside storehouse
    33        front of study door
    34        study
    35        empty study
    36        Geo-technics office
    37        Geo-technics lab

Locations 50 and above are used in the epilogue and special disk scenario.
To avoid spoilers, I will not detail these. Location numbers for the 
<subroute> scripts mentioned above to not refer to the above list, but
instead refer to different locations within where the <subroute> scripts
take place.

<id> is there just to allow for multiple scripts per route/location 
combination. Typically, the <id>s go in chronological order along the route's
general timeflow. Scripts without and <id> are typically the last-ocurring
script for the particular route/location.

<sub_id> is a capital letter (starting with A) that can occur after the <id>.
I believe it is for variations among scripts that occur very close to 
one another chronologically for the particular route/location.

The I that can appear at the end of the script name is used to indicated 
scripts that contain the lines that are displayed when you use items. For
these, the route doesn't really matter so most of them are thrown in with the
Mitsuki script files (having no route letter).

Other script files that do not have the above format are usually for special
events/screens, i.e. opening, ending, map, menus, etc.



regarding possibility of a voice patch:

One neat application of being able to add additional commands to the script
dumps is that it is possible to transplant the voice files from the Saturn
version of the game. Doing so, however requires a bit of setup.

First, copy the VOICE.ABL files from each of the 3 Saturn discs. In order to 
extract and convert these into something which the Windows exe knows how to 
use, it will require some external tools.

Head to http://www.dsl.gr.jp/~sage/sagepage/prog/ and download the following
tools:

MCUT (mcut1101.lzh)
ACMCNV (acmcnv12.lzh)

First use MCUT on the VOICE.ABL files to generate a list of offsets/sizes
of all the voice data in the archives.

Specific command-line (w/ voice archive renamed to VOICE_A.ABL):
    MCUT -t aiff VOICE_A.ABL > <list_file>

After the list file has been generated, you can use ACMCNV to dump out
converted .wav files from the voice archive.

Here's how to do this:
    ACMCNV -C <output_dir> -l <list_file>
	
The ACMCNV tool will dump out 16-bit mono 18900 Hz PCM wav files. The
nonstandard sample rate used here is a bit of a problem, since the game
engine's sound effect command seems to play back at 22050 Hz no matter what. 
Therefore, resampling is necessary.

A convenient tool to do the resampling is SoX (http://sox.sourceforge.net/).

To resample an individual wav file, do:
    sox <input_wav> -r 22050 <output_wav>

You'll want to script this command over all the voice tracks. In the Windows
command shell, you can do this by:
    for %f in (*.wav) do sox %f -r 22050 <output_dir>\%f

Once the files are converted, place them somewhere within the game directory.
These will be played as sound commands so we need to have the game read the
files directly rather than from an archive. To do so, make the following
change to AI5WIN.INI:

[FILE]
bARCEFFECT=1 change to bARCEFFECT=0

Since we are no longer reading from EFFECT.ARC, use crass to extract the 
individual sound effect files in the same manner as MES.ARC. Copy the 
resulting .WAV files to the base game directory where the executable 
resides.

To have the game engine play the voice files, you need to place a sound
effect command before each of the relevant text commands.

The format of these sound commands is the following:
0D 05 FF 02 03 FF 01 "<path_to>\<wav_file>" 02 00 FF 00

Unforunately, I don't have reasonable way of matching up the voice files
with the text. To do so would require decompressing and reversing the Saturn 
version's script file format.



nocd patch:

Apply to AI5WIN.EXE (483,328 bytes) inside game directory.

0x15978: E8 9B B7 FE FF --> 90 90 90 90 90
0x1597F: 75 --> EB

before/after md5s:
    before   17c4e31a32c8814d6649922105119b22
	after    bc7b3eded03cb886814bc747c0881a51

